function coeffs=bciGetSpatialFilterCoeffs(cap,nThresh,chanList,method)
% coeffs=bciGetSpatialFilterCoeffs(cap,neighborThresh,chanList)
% returns a nChan X nChan coefficient Matrix, where each row contains
% spatial filter coefficients for each channel
% cap 1 - bioSemi 64 electrodes (default)
% cap 2 - easyCap 29 electrodes
% cap 3 - brainProducts cap 64 electrodes
% cap 4 - BTI 248 MEG sensors  
% cap 5 - Walter EEG cap 64 electrodes
% cap 6 - Walter EEG cap 64 electrodes
% neighborThresh (optional) - cone angle for capturing adjacent channels
% (in radians) 
% chanList (optional) - channels to include, also for resorting
% method (optional) - 'laplace' (default) or 'gauss'

if nargin < 1,
    cap=1;
end
if nargin<4,
    method='laplace';
end

isPolar=true;

switch cap,
    case 1, 
        coord=getBioSemiPolarCoords;
        neighborThresh=0.5;
    case 2, 
        coord=getEasyCap29PolarCoords;
        neighborThresh=0.8;
    case 3,
        coord=getBrainAmpPolarCoords;
        neighborThresh=0.5;
    case 4,
        coord=getBTISphericalCoords;
        neighborThresh=0.25;
        isPolar = false;
    case 5,
        coord=getWalterPolarCoords;
        neighborThresh=0.5;
    case 6,
        coord=getWalterPolarCoords;
        coord=coord(1:32,:);
        neighborThresh=0.8;
end

if nargin>1 && ~isempty(nThresh),
    neighborThresh = nThresh;
end

if nargin>2,
    coord=coord(chanList,:);
end

if isPolar,
    coord=pi*coord./180; % convert to rad
    % convert to spherical polar coordinates
    posInc=coord(:,1)>=0; 
    posAzi=coord(:,2)>=0; 
    coord(posInc,1)=pi/2-coord(posInc,1);
    coord(~posInc,1)=pi/2+coord(~posInc,1);
    coord(~posInc&~posAzi,2)=pi+coord(~posInc&~posAzi,2);
    coord(~posInc&posAzi,2)=-pi+coord(~posInc&posAzi,2);
end

% create adjacent matrices
n=size(coord,1);
Phi1=coord(:,1)*ones(1,n);
Phi2=ones(n,1)*coord(:,1)';
Lambda1=coord(:,2)*ones(1,n);
Lambda2=ones(n,1)*coord(:,2)';

% get pairwise distances in rad
dL=Lambda2-Lambda1;
dP=Phi2-Phi1;

% Formula for great circle distance
a = sin(dP./2).^2+cos(Phi1).*cos(Phi2).*sin(dL./2).^2;
distance = 2 * atan2(sqrt(a), sqrt(1-a));


if ~isempty(strfind(method,'laplac')),
    % find the direct neighbors
    neighbors = distance<neighborThresh & distance>0;
    %nNeighbors = sum(neighbors,2);
    sumNeighborDist = sum(distance.*neighbors,2);
    if any(sumNeighborDist==0),
        warning('Electrodes without neighbors found.');
        sumNeighborDist(sumNeighborDist==0)=Inf;
    end
    normNeighborDist = distance./((sumNeighborDist)*ones(1,n));
    % get the Laplacian coeffs
    % coeffs = -1./(nNeighbors*ones(1,n)).*neighbors+eye(n); % each neighbor weighted equally
    coeffs = -normNeighborDist.*neighbors+eye(n); % take distance into account
elseif ~isempty(strfind(method,'gauss')),
    % get gaussian coeffs
    fwhm = neighborThresh;
    sigma=fwhm/(2*sqrt(2*log(2)));
    coeffs = exp(-distance.^2/(2*sigma^2)) / (sqrt(2*pi)*sigma);
    % normalize
    coeffs = coeffs ./ repmat(sum(coeffs,2),1,size(coeffs,2));
else
    error('Spatial filter Method unknown');
end


% ------------------- get the coordinates for BioSemi Cap 64 electrodes
function coord = getBioSemiPolarCoords()
coord=...
[-92,-72;...Fp1
-92,-54;... AF7
-74	-65;... AF3
-50	-68;... F1
-60	-51;... F3
-75	-41;... F5
-92	-36;... F7
-92	-18;... FT7
-72	-21;... FC5
-50	-28;... FC3
-32	-45;... FC1
-23	0;...   C1
-46	0;...   C3
-69	0;...   C5
-92	0;...   T7
-92	18;...  TP7
-72	21;...  CP5
-50	28;...  CP3
-32	45;...  CP1
-50	68;...  P1
-60	51;...  P3
-75	41;...  P5
-92	36;...  P7
-115,40;... P9
-92	54;...  PO7
-74	65;...  PO3
-92	72;...  O1
115	-90;... Iz
92	-90;...  Oz
69	-90;...  POz
46	-90;...  Pz
23	-90;...  CPz
92	90;...   Fpz
92	72;...   Fp2
92	54;...   AF8
74	65;...   AF4
69	90;...   Afz
46	90;...   Fz
50	68;...   F2
60	51;...   F4
75	41;...   F6
92	36;...   F8
92	18;...   FT8
72	21;...   FC6
50	28;...   FC4
32	45;...   FC2
23	90;...   FCz
0	0;...     Cz
23	0;...    C2
46	0;...    C4
69	0;...    C6
92	0;...    T8
92	-18;...  TP8
72	-21;...  CP6
50	-28;...  CP4
32	-45;...  CP2
50	-68;...  P2
60	-51;...  P4
75	-41;...  P6
92	-36;...  P8
115	-40;... P10
92	-54;...  PO8
74	-65;...  PO4
92	-72;...  O2
];

% ------------------- get the coordinates for Easy Cap 29 electrodes
function coord = getEasyCap29PolarCoords()
% channel order sorted from E1 to E29
coord=...
[46	90;...  Fz
0	0;...     Cz
46	-90;... Pz
92	-90;... Oz
115	-90;... Iz
-92	-72;... Fp1
92	72;...  Fp2
-60	-51;... F3
60	51;...  F4
-92	-36;... F7
92	36;...  F8
-92	0;...   T7
92	0;...   T8
-46	0;...   C3
46	0;...   C4
-60	51;...  P3
60	-51;... P4
-115	72;...O9
115	-72;... O10
-92	36;...  P7
92	-36;... P8
-32	-45;... FC1
32	45;...  FC2
-32	45;...  CP1
32	-45;... CP2
-74	65;...  PO3
74	-65;... PO4
-92	54;...  PO7
92	-54 ... PO8
];

% ------------------- get the coordinates for BrainAmp 64 electrodes
function coord = getBrainAmpPolarCoords()
coord=...
[-92	-72	;	...	Fp1
92	72	;	...	Fp2
-60	-51	;	...	F3 
60	51	;	...	F4
-46	0	;	...	C3
46	0	;	...	C4
-60	51	;	...	P3
60	-51	;	...	P4
-92	72	;	...	O1
92	-72	;	...	O2
-92	-36	;	...	F7
92	36	;	...	F8
-92	0	;	...	T7
92	0	;	...	T8
-92	36	;	...	P7
92	-36	;	...	P8
46	90	;	...	Fz
0	0	;	...	Cz
46	-90	;	...	Pz
92	-90	;	...	Oz
-32	-45	;	...	FC1
32	45	;	...	FC2
-32	45	;	...	CP1
32	-45	;	...	CP2
-72	-21	;	...	FC5
72	21	;	...	FC6
-72	21	;	...	CP5
72	-21	;	...	CP6
-113	18	;	...	TP9
-130	80	;	...	IO 
-119	-36	;	...	LE (position unsure)
119	36	;	...	RE  (position unsure)
-50	-68	;	...	F1
50	68	;	...	F2
-23	0	;	...	C1
23	0	;	...	C2
-50	68	;	...	P1
50	-68	;	...	P2
-74	-65	;	...	AF3
74	65	;	...	AF4
-50	-28	;	...	FC3
50	28	;	...	FC4
-50	28	;	...	CP3
50	-28	;	...	CP4
-74	65	;	...	PO3
74	-65	;	...	PO4
-75	-41	;	...	F5
75	41	;	...	F6
-69	0	;	...	C5
69	0	;	...	C6
-75	41	;	...	P5
75	-41	;	...	P6
-92	-54	;	...	AF7
92	54	;	...	AF8
-92	-18	;	...	FT7
92	18	;	...	FT8
-92	18	;	...	TP7
92	-18	;	...	TP8
-92	54	;	...	PO7
92	-54	;	...	PO8
92	90	;	...	Fpz
23	90	;	...	FCz
23	-90	;	...	CPz
69	-90	;	...	POz
];

function coord=getWalterPolarCoords()
coord = [
23	-90
72	-21
-32	45
32	-45
-72	-21
72	21 
-32	-45
32	45 
92	-90
-72	21
23	90 
-115	0
-92	-36
-92	36
-92	-72
-60	51
-92	72
46	-90
60	51 
92	-72
92	0  
115	0 
-92	0 
-60	-51
-46	0 
46	90 
0	0   
46	0  
92	72 
60	-51
92	-36
92	36 
-92	18
92	-18
-92	-18
92	18 
74	-65
83	-60
-72	77
72	-77
-83	60
92	-54
-92	54
-74	65
-23	0 
50	-28
-74	-65
75	41 
50	28 
50	-68
74	65 
-50	-28
23	0  
75	-41
69	0  
92	54 
-50	-68
-50	68
-75	41
-75	-41
-92	-54
50	68 
-50	28
-69	0 
];

function coord = getBTISphericalCoords()
% channel order sorted from A1 to A248
coord=[
  -9.1     +7.1   +156.9
 +12.4     +6.0   +157.2
 +36.6     +6.7   +155.1
 +57.9     +6.1   +152.7
 +78.7     +5.2   +146.8
 +78.7    +25.8   +144.4
 +58.1    +28.8   +148.2
 +36.7    +30.0   +151.0
 +14.3    +30.5   +153.3
  -8.2    +28.3   +155.0
 -29.5    +28.3   +152.6
 -31.2     +7.3   +155.0
 -29.4    -13.0   +153.9
 -10.2    -15.9   +155.9
 +11.6    -17.0   +155.1
 +35.4    -17.3   +152.2
 +56.7    -17.9   +150.8
 +78.2    -16.5   +146.5
 +98.6     +3.0   +138.9
 +97.5    +29.6   +135.4
 +81.2    +46.3   +135.6
 +57.1    +49.7   +139.4
 +37.5    +52.1   +140.6
 +14.8    +53.6   +143.0
  -7.5    +52.9   +145.5
 -33.2    +49.7   +143.2
 -50.3    +31.9   +144.4
 -53.3     +7.2   +146.1
 -50.9    -16.3   +145.9
 -34.4    -34.4   +146.9
 -10.6    -38.3   +148.9
 +11.9    -40.1   +147.4
 +35.2    -40.9   +145.1
 +54.7    -40.2   +143.4
 +79.1    -38.1   +140.1
 +96.4    -22.6   +137.3
+116.2     +2.0   +125.4
+114.9    +26.2   +122.6
+100.5    +47.6   +124.0
 +81.3    +63.0   +123.1
 +60.6    +67.5   +125.6
 +39.9    +69.7   +127.0
 +18.8    +71.7   +128.5
  -1.7    +71.3   +131.8
 -24.0    +69.9   +131.8
 -45.4    +61.7   +130.1
 -61.1    +47.6   +130.5
 -69.8    +27.9   +133.9
 -73.4     +6.5   +134.5
 -70.1    -13.6   +135.2
 -61.9    -33.1   +135.3
 -46.4    -47.9   +135.4
 -26.5    -55.4   +137.6
  -6.3    -58.1   +137.1
 +14.9    -60.8   +134.6
 +37.1    -60.1   +133.2
 +57.0    -58.9   +131.9
 +78.4    -55.8   +129.0
 +98.7    -41.6   +127.6
+113.4    -21.2   +124.5
+130.0     +0.9   +108.1
+127.9    +25.2   +106.4
+117.9    +47.1   +105.8
+101.9    +65.1   +105.7
 +81.7    +77.8   +105.5
 +58.0    +83.0   +107.2
 +37.4    +85.5   +108.3
 +14.5    +87.7   +109.5
  -6.8    +87.7   +113.0
 -27.7    +85.2   +113.1
 -47.5    +77.7   +113.6
 -65.3    +64.6   +114.3
 -78.5    +48.2   +114.8
 -86.8    +28.9   +115.8
 -90.2     +8.7   +116.9
 -88.4    -13.4   +118.4
 -80.0    -33.4   +119.0
 -67.7    -51.1   +119.5
 -51.0    -63.9   +120.1
 -32.8    -72.5   +120.4
 -10.9    -76.3   +120.7
 +10.7    -78.1   +116.8
 +32.7    -77.8   +115.8
 +53.6    -76.4   +115.0
 +77.6    -72.8   +112.5
 +99.5    -61.0   +110.8
+115.8    -43.7   +109.4
+126.7    -22.5   +108.2
+139.8     -0.3    +89.2
+137.8    +23.2    +86.8
+129.7    +44.0    +87.2
+117.2    +62.4    +86.8
+101.0    +77.2    +85.9
 +80.7    +88.3    +85.1
 +58.1    +93.0    +86.3
 +37.8    +95.3    +87.0
 +15.7    +98.1    +87.8
  -7.0    +98.3    +91.8
 -27.0    +96.5    +92.4
 -47.0    +90.4    +92.4
 -65.8    +79.1    +93.3
 -80.8    +65.0    +93.6
 -92.6    +47.1    +94.5
 -99.1    +27.5    +94.8
-103.0     +7.6    +95.8
-101.2    -13.8    +96.9
 -94.4    -34.4    +98.2
 -83.5    -52.4    +98.9
 -69.3    -67.2    +99.4
 -52.3    -78.7    +99.8
 -32.5    -86.5   +100.1
 -11.8    -89.5   +100.6
 +10.1    -90.7    +95.8
 +32.5    -89.5    +95.8
 +53.2    -88.7    +95.4
 +76.8    -84.7    +93.5
 +97.2    -75.2    +93.2
+114.5    -60.7    +92.0
+127.6    -43.0    +91.4
+136.7    -21.8    +89.3
+144.9     -0.2    +67.8
+142.3    +23.1    +67.1
+134.0    +45.6    +65.9
+121.0    +64.8    +65.4
+103.2    +80.9    +65.3
 +81.5    +92.2    +64.6
 +57.7    +97.5    +64.5
 +38.2   +100.0    +64.4
 +15.1   +102.8    +64.7
  -6.8   +104.3    +70.1
 -28.4   +102.4    +69.5
 -49.6    +96.0    +70.1
 -70.0    +84.0    +71.0
 -86.4    +68.3    +71.3
 -98.8    +49.6    +71.8
-106.7    +28.9    +73.1
-110.0     +6.5    +74.0
-107.8    -16.2    +75.5
-100.3    -38.1    +76.6
 -89.0    -57.5    +77.9
 -73.5    -73.4    +78.8
 -55.3    -85.8    +79.0
 -33.8    -94.3    +79.5
 -11.9    -97.1    +80.4
  +9.5    -97.5    +74.6
 +32.3    -96.3    +74.4
 +53.2    -95.3    +73.7
 +77.7    -90.6    +73.5
 +99.0    -81.0    +72.8
+118.5    -64.9    +71.3
+132.4    -46.9    +70.2
+141.5    -24.2    +69.2
 +97.0    +85.5    +44.9
 +79.1    +93.6    +43.0
 +56.1    +98.4    +42.4
 +31.1   +106.0    +36.8
  +9.1   +108.5    +37.1
 -12.0   +111.1    +36.6
 -39.2   +101.2    +50.8
 -60.2    +92.4    +50.6
 -79.5    +77.9    +51.4
 -94.6    +60.3    +51.1
-105.1    +39.9    +52.8
-110.8    +17.9    +53.9
-111.5     -6.0    +55.0
-106.5    -29.0    +56.3
 -97.1    -50.4    +57.5
 -82.5    -69.1    +58.8
 -65.1    -83.6    +58.7
 -44.7    -94.0    +59.5
 -18.3   -107.1    +46.8
  +3.5   -105.6    +46.7
 +25.9   -104.1    +46.4
 +52.1    -97.4    +50.8
 +74.2    -93.7    +50.9
 +93.5    -86.3    +51.7
 +94.8    +88.4    +19.5
 +76.4    +96.1    +20.5
 +56.1    +97.7    +20.4
 -28.8   +113.1    +22.2
 -50.4    +96.8    +33.1
 -70.6    +85.6    +33.0
 -87.9    +69.1    +34.2
-100.5    +50.3    +35.2
-109.0    +28.2    +35.0
-112.2     +4.8    +36.7
-109.7    -19.9    +37.6
-103.3    -40.6    +38.7
 -90.8    -61.6    +40.6
 -74.4    -78.4    +41.1
 -55.7    -90.5    +41.8
 -35.0   -109.3    +33.3
 +51.6    -98.4    +29.1
 +71.3    -97.7    +30.2
 +90.6    -91.1    +31.2
 +31.6   +105.5     +8.8
  +9.8   +108.2     +8.6
 -12.6   +110.9     +8.9
 -60.5    +91.5    +14.4
 -80.0    +77.2    +15.6
 -95.5    +60.0    +16.7
-106.6    +38.1    +18.2
-110.6    +15.3    +19.1
-112.5     -7.1    +20.2
-106.7    -31.3    +21.5
 -97.3    -52.4    +21.6
 -83.2    -71.0    +23.0
 -65.5    -86.0    +23.2
 -18.4   -109.7    +18.9
  +3.9   -107.7    +18.6
 +25.8   -106.0    +18.6
 +78.7    +91.6     -0.4
 +56.4    +96.7     -1.0
 -29.3   +112.2     -6.5
 -50.7    +95.2     -4.4
 -70.2    +84.4     -3.9
 -88.2    +68.5     -2.6
-101.3    +48.8     -1.5
-110.2    +26.3     +0.3
-111.9     +3.3     +1.0
-110.3    -20.9     +1.7
-103.1    -42.8     +2.3
 -91.1    -62.7     +3.8
 -75.2    -79.9     +4.1
 -56.0    -92.8     +4.6
 -34.5   -111.2     +5.1
 +51.7    -99.4     +7.5
 +73.5    -95.9     +7.7
 +73.7    +95.5    -20.7
 +49.1    +99.9    -22.8
 +31.5   +104.5    -19.2
  +9.5   +107.4    -20.0
 -13.2   +110.3    -19.7
 -61.2    +88.4    -22.8
 -80.2    +76.3    -22.8
 -94.7    +57.7    -20.5
-106.5    +37.6    -19.9
-112.6    +14.4    -18.4
-112.6     -9.8    -18.6
-106.9    -33.0    -17.2
 -97.6    -53.7    -15.8
 -83.9    -72.8    -14.8
 -65.4    -87.7    -13.9
 -17.9   -111.1     -9.1
  +4.0   -109.5     -9.6
 +26.4   -107.6     -9.8
 +44.1   -104.1    -12.1
 +67.6   -101.7    -12.3
 ];
[TH,PHI] = cart2sph(coord(:,1),coord(:,2),coord(:,3));
coord=[PHI,TH];
